// The Swift Programming Language
// https://docs.swift.org/swift-book

import ObjCPDFium

@MainActor
open class IAPDFKit {
    public static let shared = IAPDFKit()
    
    private init() {}
    
    /// 合并输出单页面
    /// - Parameters:
    /// - inputURL: 输入 PDF 文件路径
    /// - password: PDF 密码
    /// - onProgress: 进度回调，0.0 ~ 1.0
    /// - Returns: 输出 PDF 文件路径
    public func mergeSinglePage(
        _ inputURL: URL,
        password: String? = nil,
        onProgress: (@Sendable (Double) -> Void)? = nil) throws -> Task<URL, Error> {
            
            guard FileManager.default.fileExists(atPath: inputURL.path) else {
                throw IAPDFError.fileNotFound
            }
            
            return Task.detached(priority: .userInitiated) {
                do {
                    try Task.checkCancellation()
                    
                    guard let pdfiumDoc = PDFiumDocument(url: inputURL, password: password) else {
                        throw IAPDFError.loadFailed
                    }
                    
                    let outURL = FileManager.default.temporaryDirectory
                        .appendingPathComponent(UUID().uuidString)
                        .appendingPathExtension("pdf")
                    
                    // 透传 ObjC 层进度与取消
                    let ok = pdfiumDoc.mergeAllPagesToSinglePageVertical(
                        withOutputURL: outURL,
                        onProgress: { progress in
                            Task { @MainActor in
                                onProgress?(progress)
                            }
                        },
                        isCancelled: {
                            Task.isCancelled
                        }
                    )
                    
                    // 如果在 ObjC 层因取消提前返回，这里可观察到取消标记
                    if Task.isCancelled {
                        throw IAPDFError.cancel
                    }
                    
                    if !ok {
                        throw IAPDFError.pdfWriteFileFailed
                    }
                    
                    return await MainActor.run { outURL }
                } catch is CancellationError {
                    throw IAPDFError.cancel
                }
            }
        }
}
